// Copyright (C) 2011 by Yehuda Katz
// Licensing details in LICENSE.handlebars

// lib/handlebars/base.js
/* eslint-disable */
var Handlebars = {};

Handlebars.VERSION = '1.0.beta.6';

Handlebars.helpers = {};
Handlebars.partials = {};

Handlebars.registerHelper = function (name, fn, inverse) {
  if (inverse) {
    fn.not = inverse;
  }
  this.helpers[name] = fn;
};

Handlebars.registerPartial = function (name, str) {
  this.partials[name] = str;
};

Handlebars.registerHelper('helperMissing', function (arg) {
  if (arguments.length === 2) {
    return undefined;
  } else {
    throw new Error("Could not find property '" + arg + "'");
  }
});

var toString = Object.prototype.toString,
  functionType = '[object Function]';

Handlebars.registerHelper('blockHelperMissing', function (context, options) {
  var inverse = options.inverse || function () {},
    fn = options.fn;

  var ret = '';
  var type = toString.call(context);

  if (type === functionType) {
    context = context.call(this);
  }

  if (context === true) {
    return fn(this);
  } else if (context === false || context == null) {
    return inverse(this);
  } else if (type === '[object Array]') {
    if (context.length > 0) {
      for (var i = 0, j = context.length; i < j; i++) {
        ret = ret + fn(context[i]);
      }
    } else {
      ret = inverse(this);
    }
    return ret;
  } else {
    return fn(context);
  }
});

Handlebars.registerHelper('each', function (context, options) {
  var fn = options.fn,
    inverse = options.inverse;
  var ret = '';

  if (context && context.length > 0) {
    for (var i = 0, j = context.length; i < j; i++) {
      ret = ret + fn(context[i]);
    }
  } else {
    ret = inverse(this);
  }
  return ret;
});

Handlebars.registerHelper('if', function (context, options) {
  var type = toString.call(context);
  if (type === functionType) {
    context = context.call(this);
  }

  if (!context || Handlebars.Utils.isEmpty(context)) {
    return options.inverse(this);
  } else {
    return options.fn(this);
  }
});

Handlebars.registerHelper('unless', function (context, options) {
  var fn = options.fn,
    inverse = options.inverse;
  options.fn = inverse;
  options.inverse = fn;

  return Handlebars.helpers['if'].call(this, context, options);
});

Handlebars.registerHelper('with', function (context, options) {
  return options.fn(context);
});

Handlebars.registerHelper('log', function (context) {
  Handlebars.log(context);
});
// lib/handlebars/compiler/parser.js
/* Jison generated parser */
var handlebars = (function () {
  var parser = {
    trace: function trace() {},
    yy: {},
    symbols_: {
      error: 2,
      root: 3,
      program: 4,
      EOF: 5,
      statements: 6,
      simpleInverse: 7,
      statement: 8,
      openInverse: 9,
      closeBlock: 10,
      openBlock: 11,
      mustache: 12,
      partial: 13,
      CONTENT: 14,
      COMMENT: 15,
      OPEN_BLOCK: 16,
      inMustache: 17,
      CLOSE: 18,
      OPEN_INVERSE: 19,
      OPEN_ENDBLOCK: 20,
      path: 21,
      OPEN: 22,
      OPEN_UNESCAPED: 23,
      OPEN_PARTIAL: 24,
      params: 25,
      hash: 26,
      param: 27,
      STRING: 28,
      INTEGER: 29,
      BOOLEAN: 30,
      hashSegments: 31,
      hashSegment: 32,
      ID: 33,
      EQUALS: 34,
      pathSegments: 35,
      SEP: 36,
      $accept: 0,
      $end: 1
    },
    terminals_: {
      2: 'error',
      5: 'EOF',
      14: 'CONTENT',
      15: 'COMMENT',
      16: 'OPEN_BLOCK',
      18: 'CLOSE',
      19: 'OPEN_INVERSE',
      20: 'OPEN_ENDBLOCK',
      22: 'OPEN',
      23: 'OPEN_UNESCAPED',
      24: 'OPEN_PARTIAL',
      28: 'STRING',
      29: 'INTEGER',
      30: 'BOOLEAN',
      33: 'ID',
      34: 'EQUALS',
      36: 'SEP'
    },
    productions_: [
      0,
      [3, 2],
      [4, 3],
      [4, 1],
      [4, 0],
      [6, 1],
      [6, 2],
      [8, 3],
      [8, 3],
      [8, 1],
      [8, 1],
      [8, 1],
      [8, 1],
      [11, 3],
      [9, 3],
      [10, 3],
      [12, 3],
      [12, 3],
      [13, 3],
      [13, 4],
      [7, 2],
      [17, 3],
      [17, 2],
      [17, 2],
      [17, 1],
      [25, 2],
      [25, 1],
      [27, 1],
      [27, 1],
      [27, 1],
      [27, 1],
      [26, 1],
      [31, 2],
      [31, 1],
      [32, 3],
      [32, 3],
      [32, 3],
      [32, 3],
      [21, 1],
      [35, 3],
      [35, 1]
    ],
    performAction: function anonymous(
      yytext,
      yyleng,
      yylineno,
      yy,
      yystate,
      $$,
      _$
    ) {
      var $0 = $$.length - 1;
      switch (yystate) {
        case 1:
          return $$[$0 - 1];
          break;
        case 2:
          this.$ = new yy.ProgramNode($$[$0 - 2], $$[$0]);
          break;
        case 3:
          this.$ = new yy.ProgramNode($$[$0]);
          break;
        case 4:
          this.$ = new yy.ProgramNode([]);
          break;
        case 5:
          this.$ = [$$[$0]];
          break;
        case 6:
          $$[$0 - 1].push($$[$0]);
          this.$ = $$[$0 - 1];
          break;
        case 7:
          this.$ = new yy.InverseNode($$[$0 - 2], $$[$0 - 1], $$[$0]);
          break;
        case 8:
          this.$ = new yy.BlockNode($$[$0 - 2], $$[$0 - 1], $$[$0]);
          break;
        case 9:
          this.$ = $$[$0];
          break;
        case 10:
          this.$ = $$[$0];
          break;
        case 11:
          this.$ = new yy.ContentNode($$[$0]);
          break;
        case 12:
          this.$ = new yy.CommentNode($$[$0]);
          break;
        case 13:
          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
          break;
        case 14:
          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
          break;
        case 15:
          this.$ = $$[$0 - 1];
          break;
        case 16:
          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1]);
          break;
        case 17:
          this.$ = new yy.MustacheNode($$[$0 - 1][0], $$[$0 - 1][1], true);
          break;
        case 18:
          this.$ = new yy.PartialNode($$[$0 - 1]);
          break;
        case 19:
          this.$ = new yy.PartialNode($$[$0 - 2], $$[$0 - 1]);
          break;
        case 20:
          break;
        case 21:
          this.$ = [[$$[$0 - 2]].concat($$[$0 - 1]), $$[$0]];
          break;
        case 22:
          this.$ = [[$$[$0 - 1]].concat($$[$0]), null];
          break;
        case 23:
          this.$ = [[$$[$0 - 1]], $$[$0]];
          break;
        case 24:
          this.$ = [[$$[$0]], null];
          break;
        case 25:
          $$[$0 - 1].push($$[$0]);
          this.$ = $$[$0 - 1];
          break;
        case 26:
          this.$ = [$$[$0]];
          break;
        case 27:
          this.$ = $$[$0];
          break;
        case 28:
          this.$ = new yy.StringNode($$[$0]);
          break;
        case 29:
          this.$ = new yy.IntegerNode($$[$0]);
          break;
        case 30:
          this.$ = new yy.BooleanNode($$[$0]);
          break;
        case 31:
          this.$ = new yy.HashNode($$[$0]);
          break;
        case 32:
          $$[$0 - 1].push($$[$0]);
          this.$ = $$[$0 - 1];
          break;
        case 33:
          this.$ = [$$[$0]];
          break;
        case 34:
          this.$ = [$$[$0 - 2], $$[$0]];
          break;
        case 35:
          this.$ = [$$[$0 - 2], new yy.StringNode($$[$0])];
          break;
        case 36:
          this.$ = [$$[$0 - 2], new yy.IntegerNode($$[$0])];
          break;
        case 37:
          this.$ = [$$[$0 - 2], new yy.BooleanNode($$[$0])];
          break;
        case 38:
          this.$ = new yy.IdNode($$[$0]);
          break;
        case 39:
          $$[$0 - 2].push($$[$0]);
          this.$ = $$[$0 - 2];
          break;
        case 40:
          this.$ = [$$[$0]];
          break;
      }
    },
    table: [
      {
        3: 1,
        4: 2,
        5: [2, 4],
        6: 3,
        8: 4,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 11],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      { 1: [3] },
      { 5: [1, 16] },
      {
        5: [2, 3],
        7: 17,
        8: 18,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 19],
        20: [2, 3],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      {
        5: [2, 5],
        14: [2, 5],
        15: [2, 5],
        16: [2, 5],
        19: [2, 5],
        20: [2, 5],
        22: [2, 5],
        23: [2, 5],
        24: [2, 5]
      },
      {
        4: 20,
        6: 3,
        8: 4,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 11],
        20: [2, 4],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      {
        4: 21,
        6: 3,
        8: 4,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 11],
        20: [2, 4],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      {
        5: [2, 9],
        14: [2, 9],
        15: [2, 9],
        16: [2, 9],
        19: [2, 9],
        20: [2, 9],
        22: [2, 9],
        23: [2, 9],
        24: [2, 9]
      },
      {
        5: [2, 10],
        14: [2, 10],
        15: [2, 10],
        16: [2, 10],
        19: [2, 10],
        20: [2, 10],
        22: [2, 10],
        23: [2, 10],
        24: [2, 10]
      },
      {
        5: [2, 11],
        14: [2, 11],
        15: [2, 11],
        16: [2, 11],
        19: [2, 11],
        20: [2, 11],
        22: [2, 11],
        23: [2, 11],
        24: [2, 11]
      },
      {
        5: [2, 12],
        14: [2, 12],
        15: [2, 12],
        16: [2, 12],
        19: [2, 12],
        20: [2, 12],
        22: [2, 12],
        23: [2, 12],
        24: [2, 12]
      },
      { 17: 22, 21: 23, 33: [1, 25], 35: 24 },
      { 17: 26, 21: 23, 33: [1, 25], 35: 24 },
      { 17: 27, 21: 23, 33: [1, 25], 35: 24 },
      { 17: 28, 21: 23, 33: [1, 25], 35: 24 },
      { 21: 29, 33: [1, 25], 35: 24 },
      { 1: [2, 1] },
      {
        6: 30,
        8: 4,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 11],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      {
        5: [2, 6],
        14: [2, 6],
        15: [2, 6],
        16: [2, 6],
        19: [2, 6],
        20: [2, 6],
        22: [2, 6],
        23: [2, 6],
        24: [2, 6]
      },
      { 17: 22, 18: [1, 31], 21: 23, 33: [1, 25], 35: 24 },
      { 10: 32, 20: [1, 33] },
      { 10: 34, 20: [1, 33] },
      { 18: [1, 35] },
      {
        18: [2, 24],
        21: 40,
        25: 36,
        26: 37,
        27: 38,
        28: [1, 41],
        29: [1, 42],
        30: [1, 43],
        31: 39,
        32: 44,
        33: [1, 45],
        35: 24
      },
      {
        18: [2, 38],
        28: [2, 38],
        29: [2, 38],
        30: [2, 38],
        33: [2, 38],
        36: [1, 46]
      },
      {
        18: [2, 40],
        28: [2, 40],
        29: [2, 40],
        30: [2, 40],
        33: [2, 40],
        36: [2, 40]
      },
      { 18: [1, 47] },
      { 18: [1, 48] },
      { 18: [1, 49] },
      { 18: [1, 50], 21: 51, 33: [1, 25], 35: 24 },
      {
        5: [2, 2],
        8: 18,
        9: 5,
        11: 6,
        12: 7,
        13: 8,
        14: [1, 9],
        15: [1, 10],
        16: [1, 12],
        19: [1, 11],
        20: [2, 2],
        22: [1, 13],
        23: [1, 14],
        24: [1, 15]
      },
      {
        14: [2, 20],
        15: [2, 20],
        16: [2, 20],
        19: [2, 20],
        22: [2, 20],
        23: [2, 20],
        24: [2, 20]
      },
      {
        5: [2, 7],
        14: [2, 7],
        15: [2, 7],
        16: [2, 7],
        19: [2, 7],
        20: [2, 7],
        22: [2, 7],
        23: [2, 7],
        24: [2, 7]
      },
      { 21: 52, 33: [1, 25], 35: 24 },
      {
        5: [2, 8],
        14: [2, 8],
        15: [2, 8],
        16: [2, 8],
        19: [2, 8],
        20: [2, 8],
        22: [2, 8],
        23: [2, 8],
        24: [2, 8]
      },
      {
        14: [2, 14],
        15: [2, 14],
        16: [2, 14],
        19: [2, 14],
        20: [2, 14],
        22: [2, 14],
        23: [2, 14],
        24: [2, 14]
      },
      {
        18: [2, 22],
        21: 40,
        26: 53,
        27: 54,
        28: [1, 41],
        29: [1, 42],
        30: [1, 43],
        31: 39,
        32: 44,
        33: [1, 45],
        35: 24
      },
      { 18: [2, 23] },
      { 18: [2, 26], 28: [2, 26], 29: [2, 26], 30: [2, 26], 33: [2, 26] },
      { 18: [2, 31], 32: 55, 33: [1, 56] },
      { 18: [2, 27], 28: [2, 27], 29: [2, 27], 30: [2, 27], 33: [2, 27] },
      { 18: [2, 28], 28: [2, 28], 29: [2, 28], 30: [2, 28], 33: [2, 28] },
      { 18: [2, 29], 28: [2, 29], 29: [2, 29], 30: [2, 29], 33: [2, 29] },
      { 18: [2, 30], 28: [2, 30], 29: [2, 30], 30: [2, 30], 33: [2, 30] },
      { 18: [2, 33], 33: [2, 33] },
      {
        18: [2, 40],
        28: [2, 40],
        29: [2, 40],
        30: [2, 40],
        33: [2, 40],
        34: [1, 57],
        36: [2, 40]
      },
      { 33: [1, 58] },
      {
        14: [2, 13],
        15: [2, 13],
        16: [2, 13],
        19: [2, 13],
        20: [2, 13],
        22: [2, 13],
        23: [2, 13],
        24: [2, 13]
      },
      {
        5: [2, 16],
        14: [2, 16],
        15: [2, 16],
        16: [2, 16],
        19: [2, 16],
        20: [2, 16],
        22: [2, 16],
        23: [2, 16],
        24: [2, 16]
      },
      {
        5: [2, 17],
        14: [2, 17],
        15: [2, 17],
        16: [2, 17],
        19: [2, 17],
        20: [2, 17],
        22: [2, 17],
        23: [2, 17],
        24: [2, 17]
      },
      {
        5: [2, 18],
        14: [2, 18],
        15: [2, 18],
        16: [2, 18],
        19: [2, 18],
        20: [2, 18],
        22: [2, 18],
        23: [2, 18],
        24: [2, 18]
      },
      { 18: [1, 59] },
      { 18: [1, 60] },
      { 18: [2, 21] },
      { 18: [2, 25], 28: [2, 25], 29: [2, 25], 30: [2, 25], 33: [2, 25] },
      { 18: [2, 32], 33: [2, 32] },
      { 34: [1, 57] },
      { 21: 61, 28: [1, 62], 29: [1, 63], 30: [1, 64], 33: [1, 25], 35: 24 },
      {
        18: [2, 39],
        28: [2, 39],
        29: [2, 39],
        30: [2, 39],
        33: [2, 39],
        36: [2, 39]
      },
      {
        5: [2, 19],
        14: [2, 19],
        15: [2, 19],
        16: [2, 19],
        19: [2, 19],
        20: [2, 19],
        22: [2, 19],
        23: [2, 19],
        24: [2, 19]
      },
      {
        5: [2, 15],
        14: [2, 15],
        15: [2, 15],
        16: [2, 15],
        19: [2, 15],
        20: [2, 15],
        22: [2, 15],
        23: [2, 15],
        24: [2, 15]
      },
      { 18: [2, 34], 33: [2, 34] },
      { 18: [2, 35], 33: [2, 35] },
      { 18: [2, 36], 33: [2, 36] },
      { 18: [2, 37], 33: [2, 37] }
    ],
    defaultActions: { 16: [2, 1], 37: [2, 23], 53: [2, 21] },
    parseError: function parseError(str, hash) {
      throw new Error(str);
    },
    parse: function parse(input) {
      var self = this,
        stack = [0],
        vstack = [null],
        lstack = [],
        table = this.table,
        yytext = '',
        yylineno = 0,
        yyleng = 0,
        recovering = 0,
        TERROR = 2,
        EOF = 1;
      this.lexer.setInput(input);
      this.lexer.yy = this.yy;
      this.yy.lexer = this.lexer;
      if (typeof this.lexer.yylloc == 'undefined') this.lexer.yylloc = {};
      var yyloc = this.lexer.yylloc;
      lstack.push(yyloc);
      if (typeof this.yy.parseError === 'function')
        this.parseError = this.yy.parseError;
      function popStack(n) {
        stack.length = stack.length - 2 * n;
        vstack.length = vstack.length - n;
        lstack.length = lstack.length - n;
      }
      function lex() {
        var token;
        token = self.lexer.lex() || 1;
        if (typeof token !== 'number') {
          token = self.symbols_[token] || token;
        }
        return token;
      }
      var symbol,
        preErrorSymbol,
        state,
        action,
        a,
        r,
        yyval = {},
        p,
        len,
        newState,
        expected;
      while (true) {
        state = stack[stack.length - 1];
        if (this.defaultActions[state]) {
          action = this.defaultActions[state];
        } else {
          if (symbol == null) symbol = lex();
          action = table[state] && table[state][symbol];
        }
        if (typeof action === 'undefined' || !action.length || !action[0]) {
          if (!recovering) {
            expected = [];
            for (p in table[state])
              if (this.terminals_[p] && p > 2) {
                expected.push("'" + this.terminals_[p] + "'");
              }
            var errStr = '';
            if (this.lexer.showPosition) {
              errStr =
                'Parse error on line ' +
                (yylineno + 1) +
                ':\n' +
                this.lexer.showPosition() +
                '\nExpecting ' +
                expected.join(', ') +
                ", got '" +
                this.terminals_[symbol] +
                "'";
            } else {
              errStr =
                'Parse error on line ' +
                (yylineno + 1) +
                ': Unexpected ' +
                (symbol == 1
                  ? 'end of input'
                  : "'" + (this.terminals_[symbol] || symbol) + "'");
            }
            this.parseError(errStr, {
              text: this.lexer.match,
              token: this.terminals_[symbol] || symbol,
              line: this.lexer.yylineno,
              loc: yyloc,
              expected: expected
            });
          }
        }
        if (action[0] instanceof Array && action.length > 1) {
          throw new Error(
            'Parse Error: multiple actions possible at state: ' +
              state +
              ', token: ' +
              symbol
          );
        }
        switch (action[0]) {
          case 1:
            stack.push(symbol);
            vstack.push(this.lexer.yytext);
            lstack.push(this.lexer.yylloc);
            stack.push(action[1]);
            symbol = null;
            if (!preErrorSymbol) {
              yyleng = this.lexer.yyleng;
              yytext = this.lexer.yytext;
              yylineno = this.lexer.yylineno;
              yyloc = this.lexer.yylloc;
              if (recovering > 0) recovering--;
            } else {
              symbol = preErrorSymbol;
              preErrorSymbol = null;
            }
            break;
          case 2:
            len = this.productions_[action[1]][1];
            yyval.$ = vstack[vstack.length - len];
            yyval._$ = {
              first_line: lstack[lstack.length - (len || 1)].first_line,
              last_line: lstack[lstack.length - 1].last_line,
              first_column: lstack[lstack.length - (len || 1)].first_column,
              last_column: lstack[lstack.length - 1].last_column
            };
            r = this.performAction.call(
              yyval,
              yytext,
              yyleng,
              yylineno,
              this.yy,
              action[1],
              vstack,
              lstack
            );
            if (typeof r !== 'undefined') {
              return r;
            }
            if (len) {
              stack = stack.slice(0, -1 * len * 2);
              vstack = vstack.slice(0, -1 * len);
              lstack = lstack.slice(0, -1 * len);
            }
            stack.push(this.productions_[action[1]][0]);
            vstack.push(yyval.$);
            lstack.push(yyval._$);
            newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
            stack.push(newState);
            break;
          case 3:
            return true;
        }
      }
      return true;
    }
  }; /* Jison generated lexer */
  var lexer = (function () {
    var lexer = {
      EOF: 1,
      parseError: function parseError(str, hash) {
        if (this.yy.parseError) {
          this.yy.parseError(str, hash);
        } else {
          throw new Error(str);
        }
      },
      setInput: function (input) {
        this._input = input;
        this._more = this._less = this.done = false;
        this.yylineno = this.yyleng = 0;
        this.yytext = this.matched = this.match = '';
        this.conditionStack = ['INITIAL'];
        this.yylloc = {
          first_line: 1,
          first_column: 0,
          last_line: 1,
          last_column: 0
        };
        return this;
      },
      input: function () {
        var ch = this._input[0];
        this.yytext += ch;
        this.yyleng++;
        this.match += ch;
        this.matched += ch;
        var lines = ch.match(/\n/);
        if (lines) this.yylineno++;
        this._input = this._input.slice(1);
        return ch;
      },
      unput: function (ch) {
        this._input = ch + this._input;
        return this;
      },
      more: function () {
        this._more = true;
        return this;
      },
      pastInput: function () {
        var past = this.matched.substr(
          0,
          this.matched.length - this.match.length
        );
        return (
          (past.length > 20 ? '...' : '') + past.substr(-20).replace(/\n/g, '')
        );
      },
      upcomingInput: function () {
        var next = this.match;
        if (next.length < 20) {
          next += this._input.substr(0, 20 - next.length);
        }
        return (next.substr(0, 20) + (next.length > 20 ? '...' : '')).replace(
          /\n/g,
          ''
        );
      },
      showPosition: function () {
        var pre = this.pastInput();
        var c = new Array(pre.length + 1).join('-');
        return pre + this.upcomingInput() + '\n' + c + '^';
      },
      next: function () {
        if (this.done) {
          return this.EOF;
        }
        if (!this._input) this.done = true;

        var token, match, col, lines;
        if (!this._more) {
          this.yytext = '';
          this.match = '';
        }
        var rules = this._currentRules();
        for (var i = 0; i < rules.length; i++) {
          match = this._input.match(this.rules[rules[i]]);
          if (match) {
            lines = match[0].match(/\n.*/g);
            if (lines) this.yylineno += lines.length;
            this.yylloc = {
              first_line: this.yylloc.last_line,
              last_line: this.yylineno + 1,
              first_column: this.yylloc.last_column,
              last_column: lines
                ? lines[lines.length - 1].length - 1
                : this.yylloc.last_column + match[0].length
            };
            this.yytext += match[0];
            this.match += match[0];
            this.matches = match;
            this.yyleng = this.yytext.length;
            this._more = false;
            this._input = this._input.slice(match[0].length);
            this.matched += match[0];
            token = this.performAction.call(
              this,
              this.yy,
              this,
              rules[i],
              this.conditionStack[this.conditionStack.length - 1]
            );
            if (token) return token;
            else return;
          }
        }
        if (this._input === '') {
          return this.EOF;
        } else {
          this.parseError(
            'Lexical error on line ' +
              (this.yylineno + 1) +
              '. Unrecognized text.\n' +
              this.showPosition(),
            { text: '', token: null, line: this.yylineno }
          );
        }
      },
      lex: function lex() {
        var r = this.next();
        if (typeof r !== 'undefined') {
          return r;
        } else {
          return this.lex();
        }
      },
      begin: function begin(condition) {
        this.conditionStack.push(condition);
      },
      popState: function popState() {
        return this.conditionStack.pop();
      },
      _currentRules: function _currentRules() {
        return this.conditions[
          this.conditionStack[this.conditionStack.length - 1]
        ].rules;
      },
      topState: function () {
        return this.conditionStack[this.conditionStack.length - 2];
      },
      pushState: function begin(condition) {
        this.begin(condition);
      }
    };
    lexer.performAction = function anonymous(
      yy,
      yy_,
      $avoiding_name_collisions,
      YY_START
    ) {
      var YYSTATE = YY_START;
      switch ($avoiding_name_collisions) {
        case 0:
          if (yy_.yytext.slice(-1) !== '\\') this.begin('mu');
          if (yy_.yytext.slice(-1) === '\\')
            (yy_.yytext = yy_.yytext.substr(0, yy_.yyleng - 1)),
              this.begin('emu');
          if (yy_.yytext) return 14;

          break;
        case 1:
          return 14;
          break;
        case 2:
          this.popState();
          return 14;
          break;
        case 3:
          return 24;
          break;
        case 4:
          return 16;
          break;
        case 5:
          return 20;
          break;
        case 6:
          return 19;
          break;
        case 7:
          return 19;
          break;
        case 8:
          return 23;
          break;
        case 9:
          return 23;
          break;
        case 10:
          yy_.yytext = yy_.yytext.substr(3, yy_.yyleng - 5);
          this.popState();
          return 15;
          break;
        case 11:
          return 22;
          break;
        case 12:
          return 34;
          break;
        case 13:
          return 33;
          break;
        case 14:
          return 33;
          break;
        case 15:
          return 36;
          break;
        case 16 /*ignore whitespace*/:
          break;
        case 17:
          this.popState();
          return 18;
          break;
        case 18:
          this.popState();
          return 18;
          break;
        case 19:
          yy_.yytext = yy_.yytext
            .substr(1, yy_.yyleng - 2)
            .replace(/\\"/g, '"');
          return 28;
          break;
        case 20:
          return 30;
          break;
        case 21:
          return 30;
          break;
        case 22:
          return 29;
          break;
        case 23:
          return 33;
          break;
        case 24:
          yy_.yytext = yy_.yytext.substr(1, yy_.yyleng - 2);
          return 33;
          break;
        case 25:
          return 'INVALID';
          break;
        case 26:
          return 5;
          break;
      }
    };
    lexer.rules = [
      /^[^\x00]*?(?=(\{\{))/,
      /^[^\x00]+/,
      /^[^\x00]{2,}?(?=(\{\{))/,
      /^\{\{>/,
      /^\{\{#/,
      /^\{\{\//,
      /^\{\{\^/,
      /^\{\{\s*else\b/,
      /^\{\{\{/,
      /^\{\{&/,
      /^\{\{![\s\S]*?\}\}/,
      /^\{\{/,
      /^=/,
      /^\.(?=[} ])/,
      /^\.\./,
      /^[\/.]/,
      /^\s+/,
      /^\}\}\}/,
      /^\}\}/,
      /^"(\\["]|[^"])*"/,
      /^true(?=[}\s])/,
      /^false(?=[}\s])/,
      /^[0-9]+(?=[}\s])/,
      /^[a-zA-Z0-9_$-]+(?=[=}\s\/.])/,
      /^\[[^\]]*\]/,
      /^./,
      /^$/
    ];
    lexer.conditions = {
      mu: {
        rules: [
          3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
          22, 23, 24, 25, 26
        ],
        inclusive: false
      },
      emu: { rules: [2], inclusive: false },
      INITIAL: { rules: [0, 1, 26], inclusive: true }
    };
    return lexer;
  })();
  parser.lexer = lexer;
  return parser;
})();
if (typeof require !== 'undefined' && typeof exports !== 'undefined') {
  exports.parser = handlebars;
  exports.parse = function () {
    return handlebars.parse.apply(handlebars, arguments);
  };
  exports.main = function commonjsMain(args) {
    if (!args[1]) throw new Error('Usage: ' + args[0] + ' FILE');
    if (typeof process !== 'undefined') {
      var source = require('fs').readFileSync(
        require('path').join(process.cwd(), args[1]),
        'utf8'
      );
    } else {
      var cwd = require('file').path(require('file').cwd());
      var source = cwd.join(args[1]).read({ charset: 'utf-8' });
    }
    return exports.parser.parse(source);
  };
  if (typeof module !== 'undefined' && require.main === module) {
    exports.main(
      typeof process !== 'undefined'
        ? process.argv.slice(1)
        : require('system').args
    );
  }
}
// lib/handlebars/compiler/base.js
Handlebars.Parser = handlebars;

Handlebars.parse = function (string) {
  Handlebars.Parser.yy = Handlebars.AST;
  return Handlebars.Parser.parse(string);
};

Handlebars.print = function (ast) {
  return new Handlebars.PrintVisitor().accept(ast);
};

Handlebars.logger = {
  DEBUG: 0,
  INFO: 1,
  WARN: 2,
  ERROR: 3,
  level: 3,

  // override in the host environment
  log: function (level, str) {}
};

Handlebars.log = function (level, str) {
  Handlebars.logger.log(level, str);
};
// lib/handlebars/compiler/ast.js
(function () {
  Handlebars.AST = {};

  Handlebars.AST.ProgramNode = function (statements, inverse) {
    this.type = 'program';
    this.statements = statements;
    if (inverse) {
      this.inverse = new Handlebars.AST.ProgramNode(inverse);
    }
  };

  Handlebars.AST.MustacheNode = function (params, hash, unescaped) {
    this.type = 'mustache';
    this.id = params[0];
    this.params = params.slice(1);
    this.hash = hash;
    this.escaped = !unescaped;
  };

  Handlebars.AST.PartialNode = function (id, context) {
    this.type = 'partial';

    // TODO: disallow complex IDs

    this.id = id;
    this.context = context;
  };

  var verifyMatch = function (open, close) {
    if (open.original !== close.original) {
      throw new Handlebars.Exception(
        open.original + " doesn't match " + close.original
      );
    }
  };

  Handlebars.AST.BlockNode = function (mustache, program, close) {
    verifyMatch(mustache.id, close);
    this.type = 'block';
    this.mustache = mustache;
    this.program = program;
  };

  Handlebars.AST.InverseNode = function (mustache, program, close) {
    verifyMatch(mustache.id, close);
    this.type = 'inverse';
    this.mustache = mustache;
    this.program = program;
  };

  Handlebars.AST.ContentNode = function (string) {
    this.type = 'content';
    this.string = string;
  };

  Handlebars.AST.HashNode = function (pairs) {
    this.type = 'hash';
    this.pairs = pairs;
  };

  Handlebars.AST.IdNode = function (parts) {
    this.type = 'ID';
    this.original = parts.join('.');

    var dig = [],
      depth = 0;

    for (var i = 0, l = parts.length; i < l; i++) {
      var part = parts[i];

      if (part === '..') {
        depth++;
      } else if (part === '.' || part === 'this') {
        this.isScoped = true;
      } else {
        dig.push(part);
      }
    }

    this.parts = dig;
    this.string = dig.join('.');
    this.depth = depth;
    this.isSimple = dig.length === 1 && depth === 0;
  };

  Handlebars.AST.StringNode = function (string) {
    this.type = 'STRING';
    this.string = string;
  };

  Handlebars.AST.IntegerNode = function (integer) {
    this.type = 'INTEGER';
    this.integer = integer;
  };

  Handlebars.AST.BooleanNode = function (bool) {
    this.type = 'BOOLEAN';
    this.bool = bool;
  };

  Handlebars.AST.CommentNode = function (comment) {
    this.type = 'comment';
    this.comment = comment;
  };
})();
// lib/handlebars/utils.js
Handlebars.Exception = function (message) {
  var tmp = Error.prototype.constructor.apply(this, arguments);

  for (var p in tmp) {
    if (tmp.hasOwnProperty(p)) {
      this[p] = tmp[p];
    }
  }

  this.message = tmp.message;
};
Handlebars.Exception.prototype = new Error();

// Build out our basic SafeString type
Handlebars.SafeString = function (string) {
  this.string = string;
};
Handlebars.SafeString.prototype.toString = function () {
  return this.string.toString();
};

(function () {
  var escape = {
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#x27;',
    '`': '&#x60;'
  };

  var badChars = /&(?!\w+;)|[<>"'`]/g;
  var possible = /[&<>"'`]/;

  var escapeChar = function (chr) {
    return escape[chr] || '&amp;';
  };

  Handlebars.Utils = {
    escapeExpression: function (string) {
      // don't escape SafeStrings, since they're already safe
      if (string instanceof Handlebars.SafeString) {
        return string.toString();
      } else if (string == null || string === false) {
        return '';
      }

      if (!possible.test(string)) {
        return string;
      }
      return string.replace(badChars, escapeChar);
    },

    isEmpty: function (value) {
      if (typeof value === 'undefined') {
        return true;
      } else if (value === null) {
        return true;
      } else if (value === false) {
        return true;
      } else if (
        Object.prototype.toString.call(value) === '[object Array]' &&
        value.length === 0
      ) {
        return true;
      } else {
        return false;
      }
    }
  };
})();
// lib/handlebars/compiler/compiler.js
Handlebars.Compiler = function () {};
Handlebars.JavaScriptCompiler = function () {};

(function (Compiler, JavaScriptCompiler) {
  Compiler.OPCODE_MAP = {
    appendContent: 1,
    getContext: 2,
    lookupWithHelpers: 3,
    lookup: 4,
    append: 5,
    invokeMustache: 6,
    appendEscaped: 7,
    pushString: 8,
    truthyOrFallback: 9,
    functionOrFallback: 10,
    invokeProgram: 11,
    invokePartial: 12,
    push: 13,
    assignToHash: 15,
    pushStringParam: 16
  };

  Compiler.MULTI_PARAM_OPCODES = {
    appendContent: 1,
    getContext: 1,
    lookupWithHelpers: 2,
    lookup: 1,
    invokeMustache: 3,
    pushString: 1,
    truthyOrFallback: 1,
    functionOrFallback: 1,
    invokeProgram: 3,
    invokePartial: 1,
    push: 1,
    assignToHash: 1,
    pushStringParam: 1
  };

  Compiler.DISASSEMBLE_MAP = {};

  for (var prop in Compiler.OPCODE_MAP) {
    var value = Compiler.OPCODE_MAP[prop];
    Compiler.DISASSEMBLE_MAP[value] = prop;
  }

  Compiler.multiParamSize = function (code) {
    return Compiler.MULTI_PARAM_OPCODES[Compiler.DISASSEMBLE_MAP[code]];
  };

  Compiler.prototype = {
    compiler: Compiler,

    disassemble: function () {
      var opcodes = this.opcodes,
        opcode,
        nextCode;
      var out = [],
        str,
        name,
        value;

      for (var i = 0, l = opcodes.length; i < l; i++) {
        opcode = opcodes[i];

        if (opcode === 'DECLARE') {
          name = opcodes[++i];
          value = opcodes[++i];
          out.push('DECLARE ' + name + ' = ' + value);
        } else {
          str = Compiler.DISASSEMBLE_MAP[opcode];

          var extraParams = Compiler.multiParamSize(opcode);
          var codes = [];

          for (var j = 0; j < extraParams; j++) {
            nextCode = opcodes[++i];

            if (typeof nextCode === 'string') {
              nextCode = '"' + nextCode.replace('\n', '\\n') + '"';
            }

            codes.push(nextCode);
          }

          str = str + ' ' + codes.join(' ');

          out.push(str);
        }
      }

      return out.join('\n');
    },

    guid: 0,

    compile: function (program, options) {
      this.children = [];
      this.depths = { list: [] };
      this.options = options;

      // These changes will propagate to the other compiler components
      var knownHelpers = this.options.knownHelpers;
      this.options.knownHelpers = {
        helperMissing: true,
        blockHelperMissing: true,
        each: true,
        if: true,
        unless: true,
        with: true,
        log: true
      };
      if (knownHelpers) {
        for (var name in knownHelpers) {
          this.options.knownHelpers[name] = knownHelpers[name];
        }
      }

      return this.program(program);
    },

    accept: function (node) {
      return this[node.type](node);
    },

    program: function (program) {
      var statements = program.statements,
        statement;
      this.opcodes = [];

      for (var i = 0, l = statements.length; i < l; i++) {
        statement = statements[i];
        this[statement.type](statement);
      }
      this.isSimple = l === 1;

      this.depths.list = this.depths.list.sort(function (a, b) {
        return a - b;
      });

      return this;
    },

    compileProgram: function (program) {
      var result = new this.compiler().compile(program, this.options);
      var guid = this.guid++;

      this.usePartial = this.usePartial || result.usePartial;

      this.children[guid] = result;

      for (var i = 0, l = result.depths.list.length; i < l; i++) {
        depth = result.depths.list[i];

        if (depth < 2) {
          continue;
        } else {
          this.addDepth(depth - 1);
        }
      }

      return guid;
    },

    block: function (block) {
      var mustache = block.mustache;
      var depth, child, inverse, inverseGuid;

      var params = this.setupStackForMustache(mustache);

      var programGuid = this.compileProgram(block.program);

      if (block.program.inverse) {
        inverseGuid = this.compileProgram(block.program.inverse);
        this.declare('inverse', inverseGuid);
      }

      this.opcode('invokeProgram', programGuid, params.length, !!mustache.hash);
      this.declare('inverse', null);
      this.opcode('append');
    },

    inverse: function (block) {
      var params = this.setupStackForMustache(block.mustache);

      var programGuid = this.compileProgram(block.program);

      this.declare('inverse', programGuid);

      this.opcode('invokeProgram', null, params.length, !!block.mustache.hash);
      this.declare('inverse', null);
      this.opcode('append');
    },

    hash: function (hash) {
      var pairs = hash.pairs,
        pair,
        val;

      this.opcode('push', '{}');

      for (var i = 0, l = pairs.length; i < l; i++) {
        pair = pairs[i];
        val = pair[1];

        this.accept(val);
        this.opcode('assignToHash', pair[0]);
      }
    },

    partial: function (partial) {
      var id = partial.id;
      this.usePartial = true;

      if (partial.context) {
        this.ID(partial.context);
      } else {
        this.opcode('push', 'depth0');
      }

      this.opcode('invokePartial', id.original);
      this.opcode('append');
    },

    content: function (content) {
      this.opcode('appendContent', content.string);
    },

    mustache: function (mustache) {
      var params = this.setupStackForMustache(mustache);

      this.opcode(
        'invokeMustache',
        params.length,
        mustache.id.original,
        !!mustache.hash
      );

      if (mustache.escaped && !this.options.noEscape) {
        this.opcode('appendEscaped');
      } else {
        this.opcode('append');
      }
    },

    ID: function (id) {
      this.addDepth(id.depth);

      this.opcode('getContext', id.depth);

      this.opcode(
        'lookupWithHelpers',
        id.parts[0] || null,
        id.isScoped || false
      );

      for (var i = 1, l = id.parts.length; i < l; i++) {
        this.opcode('lookup', id.parts[i]);
      }
    },

    STRING: function (string) {
      this.opcode('pushString', string.string);
    },

    INTEGER: function (integer) {
      this.opcode('push', integer.integer);
    },

    BOOLEAN: function (bool) {
      this.opcode('push', bool.bool);
    },

    comment: function () {},

    // HELPERS
    pushParams: function (params) {
      var i = params.length,
        param;

      while (i--) {
        param = params[i];

        if (this.options.stringParams) {
          if (param.depth) {
            this.addDepth(param.depth);
          }

          this.opcode('getContext', param.depth || 0);
          this.opcode('pushStringParam', param.string);
        } else {
          this[param.type](param);
        }
      }
    },

    opcode: function (name, val1, val2, val3) {
      this.opcodes.push(Compiler.OPCODE_MAP[name]);
      if (val1 !== undefined) {
        this.opcodes.push(val1);
      }
      if (val2 !== undefined) {
        this.opcodes.push(val2);
      }
      if (val3 !== undefined) {
        this.opcodes.push(val3);
      }
    },

    declare: function (name, value) {
      this.opcodes.push('DECLARE');
      this.opcodes.push(name);
      this.opcodes.push(value);
    },

    addDepth: function (depth) {
      if (depth === 0) {
        return;
      }

      if (!this.depths[depth]) {
        this.depths[depth] = true;
        this.depths.list.push(depth);
      }
    },

    setupStackForMustache: function (mustache) {
      var params = mustache.params;

      this.pushParams(params);

      if (mustache.hash) {
        this.hash(mustache.hash);
      }

      this.ID(mustache.id);

      return params;
    }
  };

  JavaScriptCompiler.prototype = {
    // PUBLIC API: You can override these methods in a subclass to provide
    // alternative compiled forms for name lookup and buffering semantics
    nameLookup: function (parent, name, type) {
      if (/^[0-9]+$/.test(name)) {
        return parent + '[' + name + ']';
      } else if (JavaScriptCompiler.isValidJavaScriptVariableName(name)) {
        return parent + '.' + name;
      } else {
        return parent + "['" + name + "']";
      }
    },

    appendToBuffer: function (string) {
      if (this.environment.isSimple) {
        return 'return ' + string + ';';
      } else {
        return 'buffer += ' + string + ';';
      }
    },

    initializeBuffer: function () {
      return this.quotedString('');
    },

    namespace: 'Handlebars',
    // END PUBLIC API

    compile: function (environment, options, context, asObject) {
      this.environment = environment;
      this.options = options || {};

      this.name = this.environment.name;
      this.isChild = !!context;
      this.context = context || {
        programs: [],
        aliases: { self: 'this' },
        registers: { list: [] }
      };

      this.preamble();

      this.stackSlot = 0;
      this.stackVars = [];

      this.compileChildren(environment, options);

      var opcodes = environment.opcodes,
        opcode;

      this.i = 0;

      for (l = opcodes.length; this.i < l; this.i++) {
        opcode = this.nextOpcode(0);

        if (opcode[0] === 'DECLARE') {
          this.i = this.i + 2;
          this[opcode[1]] = opcode[2];
        } else {
          this.i = this.i + opcode[1].length;
          this[opcode[0]].apply(this, opcode[1]);
        }
      }

      return this.createFunctionContext(asObject);
    },

    nextOpcode: function (n) {
      var opcodes = this.environment.opcodes,
        opcode = opcodes[this.i + n],
        name,
        val;
      var extraParams, codes;

      if (opcode === 'DECLARE') {
        name = opcodes[this.i + 1];
        val = opcodes[this.i + 2];
        return ['DECLARE', name, val];
      } else {
        name = Compiler.DISASSEMBLE_MAP[opcode];

        extraParams = Compiler.multiParamSize(opcode);
        codes = [];

        for (var j = 0; j < extraParams; j++) {
          codes.push(opcodes[this.i + j + 1 + n]);
        }

        return [name, codes];
      }
    },

    eat: function (opcode) {
      this.i = this.i + opcode.length;
    },

    preamble: function () {
      var out = [];

      // this register will disambiguate helper lookup from finding a function in
      // a context. This is necessary for mustache compatibility, which requires
      // that context functions in blocks are evaluated by blockHelperMissing, and
      // then proceed as if the resulting value was provided to blockHelperMissing.
      this.useRegister('foundHelper');

      if (!this.isChild) {
        var namespace = this.namespace;
        var copies = 'helpers = helpers || ' + namespace + '.helpers;';
        if (this.environment.usePartial) {
          copies =
            copies + ' partials = partials || ' + namespace + '.partials;';
        }
        out.push(copies);
      } else {
        out.push('');
      }

      if (!this.environment.isSimple) {
        out.push(', buffer = ' + this.initializeBuffer());
      } else {
        out.push('');
      }

      // track the last context pushed into place to allow skipping the
      // getContext opcode when it would be a noop
      this.lastContext = 0;
      this.source = out;
    },

    createFunctionContext: function (asObject) {
      var locals = this.stackVars;
      if (!this.isChild) {
        locals = locals.concat(this.context.registers.list);
      }

      if (locals.length > 0) {
        this.source[1] = this.source[1] + ', ' + locals.join(', ');
      }

      // Generate minimizer alias mappings
      if (!this.isChild) {
        var aliases = [];
        for (var alias in this.context.aliases) {
          this.source[1] =
            this.source[1] + ', ' + alias + '=' + this.context.aliases[alias];
        }
      }

      if (this.source[1]) {
        this.source[1] = 'var ' + this.source[1].substring(2) + ';';
      }

      // Merge children
      if (!this.isChild) {
        this.source[1] += '\n' + this.context.programs.join('\n') + '\n';
      }

      if (!this.environment.isSimple) {
        this.source.push('return buffer;');
      }

      var params = this.isChild
        ? ['depth0', 'data']
        : ['Handlebars', 'depth0', 'helpers', 'partials', 'data'];

      for (var i = 0, l = this.environment.depths.list.length; i < l; i++) {
        params.push('depth' + this.environment.depths.list[i]);
      }

      if (asObject) {
        params.push(this.source.join('\n  '));

        return Function.apply(this, params);
      } else {
        var functionSource =
          'function ' +
          (this.name || '') +
          '(' +
          params.join(',') +
          ') {\n  ' +
          this.source.join('\n  ') +
          '}';
        Handlebars.log(Handlebars.logger.DEBUG, functionSource + '\n\n');
        return functionSource;
      }
    },

    appendContent: function (content) {
      this.source.push(this.appendToBuffer(this.quotedString(content)));
    },

    append: function () {
      var local = this.popStack();
      this.source.push(
        'if(' +
          local +
          ' || ' +
          local +
          ' === 0) { ' +
          this.appendToBuffer(local) +
          ' }'
      );
      if (this.environment.isSimple) {
        this.source.push('else { ' + this.appendToBuffer("''") + ' }');
      }
    },

    appendEscaped: function () {
      var opcode = this.nextOpcode(1),
        extra = '';
      this.context.aliases.escapeExpression = 'this.escapeExpression';

      if (opcode[0] === 'appendContent') {
        extra = ' + ' + this.quotedString(opcode[1][0]);
        this.eat(opcode);
      }

      this.source.push(
        this.appendToBuffer('escapeExpression(' + this.popStack() + ')' + extra)
      );
    },

    getContext: function (depth) {
      if (this.lastContext !== depth) {
        this.lastContext = depth;
      }
    },

    lookupWithHelpers: function (name, isScoped) {
      if (name) {
        var topStack = this.nextStack();

        this.usingKnownHelper = false;

        var toPush;
        if (!isScoped && this.options.knownHelpers[name]) {
          toPush =
            topStack + ' = ' + this.nameLookup('helpers', name, 'helper');
          this.usingKnownHelper = true;
        } else if (isScoped || this.options.knownHelpersOnly) {
          toPush =
            topStack +
            ' = ' +
            this.nameLookup('depth' + this.lastContext, name, 'context');
        } else {
          this.register(
            'foundHelper',
            this.nameLookup('helpers', name, 'helper')
          );
          toPush =
            topStack +
            ' = foundHelper || ' +
            this.nameLookup('depth' + this.lastContext, name, 'context');
        }

        toPush += ';';
        this.source.push(toPush);
      } else {
        this.pushStack('depth' + this.lastContext);
      }
    },

    lookup: function (name) {
      var topStack = this.topStack();
      this.source.push(
        topStack +
          ' = (' +
          topStack +
          ' === null || ' +
          topStack +
          ' === undefined || ' +
          topStack +
          ' === false ? ' +
          topStack +
          ' : ' +
          this.nameLookup(topStack, name, 'context') +
          ');'
      );
    },

    pushStringParam: function (string) {
      this.pushStack('depth' + this.lastContext);
      this.pushString(string);
    },

    pushString: function (string) {
      this.pushStack(this.quotedString(string));
    },

    push: function (name) {
      this.pushStack(name);
    },

    invokeMustache: function (paramSize, original, hasHash) {
      this.populateParams(
        paramSize,
        this.quotedString(original),
        '{}',
        null,
        hasHash,
        function (nextStack, helperMissingString, id) {
          if (!this.usingKnownHelper) {
            this.context.aliases.helperMissing = 'helpers.helperMissing';
            this.context.aliases.undef = 'void 0';
            this.source.push(
              'else if(' +
                id +
                '=== undef) { ' +
                nextStack +
                ' = helperMissing.call(' +
                helperMissingString +
                '); }'
            );
            if (nextStack !== id) {
              this.source.push('else { ' + nextStack + ' = ' + id + '; }');
            }
          }
        }
      );
    },

    invokeProgram: function (guid, paramSize, hasHash) {
      var inverse = this.programExpression(this.inverse);
      var mainProgram = this.programExpression(guid);

      this.populateParams(
        paramSize,
        null,
        mainProgram,
        inverse,
        hasHash,
        function (nextStack, helperMissingString, id) {
          if (!this.usingKnownHelper) {
            this.context.aliases.blockHelperMissing =
              'helpers.blockHelperMissing';
            this.source.push(
              'else { ' +
                nextStack +
                ' = blockHelperMissing.call(' +
                helperMissingString +
                '); }'
            );
          }
        }
      );
    },

    populateParams: function (
      paramSize,
      helperId,
      program,
      inverse,
      hasHash,
      fn
    ) {
      var needsRegister =
        hasHash || this.options.stringParams || inverse || this.options.data;
      var id = this.popStack(),
        nextStack;
      var params = [],
        param,
        stringParam,
        stringOptions;

      if (needsRegister) {
        this.register('tmp1', program);
        stringOptions = 'tmp1';
      } else {
        stringOptions = '{ hash: {} }';
      }

      if (needsRegister) {
        var hash = hasHash ? this.popStack() : '{}';
        this.source.push('tmp1.hash = ' + hash + ';');
      }

      if (this.options.stringParams) {
        this.source.push('tmp1.contexts = [];');
      }

      for (var i = 0; i < paramSize; i++) {
        param = this.popStack();
        params.push(param);

        if (this.options.stringParams) {
          this.source.push('tmp1.contexts.push(' + this.popStack() + ');');
        }
      }

      if (inverse) {
        this.source.push('tmp1.fn = tmp1;');
        this.source.push('tmp1.inverse = ' + inverse + ';');
      }

      if (this.options.data) {
        this.source.push('tmp1.data = data;');
      }

      params.push(stringOptions);

      this.populateCall(params, id, helperId || id, fn, program !== '{}');
    },

    populateCall: function (params, id, helperId, fn, program) {
      var paramString = ['depth0'].concat(params).join(', ');
      var helperMissingString = ['depth0']
        .concat(helperId)
        .concat(params)
        .join(', ');

      var nextStack = this.nextStack();

      if (this.usingKnownHelper) {
        this.source.push(
          nextStack + ' = ' + id + '.call(' + paramString + ');'
        );
      } else {
        this.context.aliases.functionType = '"function"';
        var condition = program ? 'foundHelper && ' : '';
        this.source.push(
          'if(' +
            condition +
            'typeof ' +
            id +
            ' === functionType) { ' +
            nextStack +
            ' = ' +
            id +
            '.call(' +
            paramString +
            '); }'
        );
      }
      fn.call(this, nextStack, helperMissingString, id);
      this.usingKnownHelper = false;
    },

    invokePartial: function (context) {
      params = [
        this.nameLookup('partials', context, 'partial'),
        "'" + context + "'",
        this.popStack(),
        'helpers',
        'partials'
      ];

      if (this.options.data) {
        params.push('data');
      }

      this.pushStack('self.invokePartial(' + params.join(', ') + ');');
    },

    assignToHash: function (key) {
      var value = this.popStack();
      var hash = this.topStack();

      this.source.push(hash + "['" + key + "'] = " + value + ';');
    },

    // HELPERS

    compiler: JavaScriptCompiler,

    compileChildren: function (environment, options) {
      var children = environment.children,
        child,
        compiler;

      for (var i = 0, l = children.length; i < l; i++) {
        child = children[i];
        compiler = new this.compiler();

        this.context.programs.push(''); // Placeholder to prevent name conflicts for nested children
        var index = this.context.programs.length;
        child.index = index;
        child.name = 'program' + index;
        this.context.programs[index] = compiler.compile(
          child,
          options,
          this.context
        );
      }
    },

    programExpression: function (guid) {
      if (guid == null) {
        return 'self.noop';
      }

      var child = this.environment.children[guid],
        depths = child.depths.list;
      var programParams = [child.index, child.name, 'data'];

      for (var i = 0, l = depths.length; i < l; i++) {
        depth = depths[i];

        if (depth === 1) {
          programParams.push('depth0');
        } else {
          programParams.push('depth' + (depth - 1));
        }
      }

      if (depths.length === 0) {
        return 'self.program(' + programParams.join(', ') + ')';
      } else {
        programParams.shift();
        return 'self.programWithDepth(' + programParams.join(', ') + ')';
      }
    },

    register: function (name, val) {
      this.useRegister(name);
      this.source.push(name + ' = ' + val + ';');
    },

    useRegister: function (name) {
      if (!this.context.registers[name]) {
        this.context.registers[name] = true;
        this.context.registers.list.push(name);
      }
    },

    pushStack: function (item) {
      this.source.push(this.nextStack() + ' = ' + item + ';');
      return 'stack' + this.stackSlot;
    },

    nextStack: function () {
      this.stackSlot++;
      if (this.stackSlot > this.stackVars.length) {
        this.stackVars.push('stack' + this.stackSlot);
      }
      return 'stack' + this.stackSlot;
    },

    popStack: function () {
      return 'stack' + this.stackSlot--;
    },

    topStack: function () {
      return 'stack' + this.stackSlot;
    },

    quotedString: function (str) {
      return (
        '"' +
        str
          .replace(/\\/g, '\\\\')
          .replace(/"/g, '\\"')
          .replace(/\n/g, '\\n')
          .replace(/\r/g, '\\r') +
        '"'
      );
    }
  };

  var reservedWords = (
    'break else new var' +
    ' case finally return void' +
    ' catch for switch while' +
    ' continue function this with' +
    ' default if throw' +
    ' delete in try' +
    ' do instanceof typeof' +
    ' abstract enum int short' +
    ' boolean export interface static' +
    ' byte extends long super' +
    ' char final native synchronized' +
    ' class float package throws' +
    ' const goto private transient' +
    ' debugger implements protected volatile' +
    ' double import public let yield'
  ).split(' ');

  var compilerWords = (JavaScriptCompiler.RESERVED_WORDS = {});

  for (var i = 0, l = reservedWords.length; i < l; i++) {
    compilerWords[reservedWords[i]] = true;
  }

  JavaScriptCompiler.isValidJavaScriptVariableName = function (name) {
    if (
      !JavaScriptCompiler.RESERVED_WORDS[name] &&
      /^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name)
    ) {
      return true;
    }
    return false;
  };
})(Handlebars.Compiler, Handlebars.JavaScriptCompiler);

Handlebars.precompile = function (string, options) {
  options = options || {};

  var ast = Handlebars.parse(string);
  var environment = new Handlebars.Compiler().compile(ast, options);
  return new Handlebars.JavaScriptCompiler().compile(environment, options);
};

Handlebars.compile = function (string, options) {
  options = options || {};

  var compiled;
  function compile() {
    var ast = Handlebars.parse(string);
    var environment = new Handlebars.Compiler().compile(ast, options);
    var templateSpec = new Handlebars.JavaScriptCompiler().compile(
      environment,
      options,
      undefined,
      true
    );
    return Handlebars.template(templateSpec);
  }

  // Template is only compiled on first use and cached after that point.
  return function (context, options) {
    if (!compiled) {
      compiled = compile();
    }
    return compiled.call(this, context, options);
  };
};
// lib/handlebars/runtime.js
Handlebars.VM = {
  template: function (templateSpec) {
    // Just add water
    var container = {
      escapeExpression: Handlebars.Utils.escapeExpression,
      invokePartial: Handlebars.VM.invokePartial,
      programs: [],
      program: function (i, fn, data) {
        var programWrapper = this.programs[i];
        if (data) {
          return Handlebars.VM.program(fn, data);
        } else if (programWrapper) {
          return programWrapper;
        } else {
          programWrapper = this.programs[i] = Handlebars.VM.program(fn);
          return programWrapper;
        }
      },
      programWithDepth: Handlebars.VM.programWithDepth,
      noop: Handlebars.VM.noop
    };

    return function (context, options) {
      options = options || {};
      return templateSpec.call(
        container,
        Handlebars,
        context,
        options.helpers,
        options.partials,
        options.data
      );
    };
  },

  programWithDepth: function (fn, data, $depth) {
    var args = Array.prototype.slice.call(arguments, 2);

    return function (context, options) {
      options = options || {};

      return fn.apply(this, [context, options.data || data].concat(args));
    };
  },
  program: function (fn, data) {
    return function (context, options) {
      options = options || {};

      return fn(context, options.data || data);
    };
  },
  noop: function () {
    return '';
  },
  invokePartial: function (partial, name, context, helpers, partials, data) {
    options = { helpers: helpers, partials: partials, data: data };

    if (partial === undefined) {
      throw new Handlebars.Exception(
        'The partial ' + name + ' could not be found'
      );
    } else if (partial instanceof Function) {
      return partial(context, options);
    } else if (!Handlebars.compile) {
      throw new Handlebars.Exception(
        'The partial ' +
          name +
          ' could not be compiled when running in runtime-only mode'
      );
    } else {
      partials[name] = Handlebars.compile(partial);
      return partials[name](context, options);
    }
  }
};

Handlebars.template = Handlebars.VM.template;
